package com.cqie.hospitalescort.service.Impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cqie.hospitalescort.DTO.AuthUser;
import com.cqie.hospitalescort.DTO.OrderDTO;
import com.cqie.hospitalescort.VO.OrderVO;
import com.cqie.hospitalescort.entity.*;
import com.cqie.hospitalescort.exception.BusinessException;
import com.cqie.hospitalescort.mapper.*;
import com.cqie.hospitalescort.service.MedOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cqie.hospitalescort.service.scheduled.ScheduledTaskService;
import com.cqie.hospitalescort.utils.DateUtil;
import com.cqie.hospitalescort.utils.WebSecurityUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单信息 服务实现类
 * </p>
 *
 * @author gdy
 * @since 2025-02-18
 */
@Service
public class MedOrderServiceImpl extends ServiceImpl<MedOrderMapper, MedOrder> implements MedOrderService {

    @Autowired
    private MedOrderMapper medOrderMapper;
    @Autowired
    private PatientInfoMapper patientInfoMapper;
    @Autowired
    private EscortInfoMapper escortInfoMapper;
    @Autowired
    private TypeMapper typeMapper;
    @Autowired
    private ScheduledTaskService scheduledTaskService;
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private AssessInfoMapper assessInfoMapper;

    /**
     * 订单列表
     *
     * @param status
     * @param isAdmin
     * @return
     */
    @Override
    public List<OrderVO> orderList(Integer status, Boolean isAdmin, Boolean isEscort) {
        AuthUser user = WebSecurityUtil.getCurrentUser();
        LambdaQueryWrapper<MedOrder> queryWrapper = new LambdaQueryWrapper<>();
        //状态(1-待接单，2-待支付，3-待陪诊，4-陪诊中，5-已完成，6-已取消)
        queryWrapper.eq(Objects.nonNull(status), MedOrder::getOrderStatus, status);
        if (!isAdmin) {

            if (Objects.nonNull(isEscort) && isEscort) {
                //陪诊员只能查询自己的数据
                queryWrapper.eq(MedOrder::getEscortId, user.getId());
            } else {
                //不是管理员、陪诊员，只查询自己的数据
                queryWrapper.eq(MedOrder::getUserId, user.getId());
            }
        }



        List<MedOrder> medOrders = medOrderMapper.selectList(queryWrapper);
        return medOrders.stream().map(order -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            orderVO.setHospitalName(order.getHospitalName());
            orderVO.setAddress(order.getAddress());
            orderVO.setNickname(userInfoMapper.selectById(order.getUserId()).getNickname());
            orderVO.setPatientInfo(patientInfoMapper.selectById(order.getPatientInfoId()));
            orderVO.setEscortInfo(escortInfoMapper.selectById(order.getEscortId()));
            Type type = typeMapper.selectById(order.getTypeId());
            List<AssessInfo> assessInfos = assessInfoMapper.selectList(
                    new LambdaQueryWrapper<AssessInfo>().eq(AssessInfo::getEscortId, order.getEscortId())
                            .eq(AssessInfo::getUserId, order.getUserId()));
            if (CollectionUtils.isNotEmpty(assessInfos)) {
                orderVO.setIsAccess(true);
            }
            if (Objects.nonNull(type)) {
                orderVO.setType(type.getTypeName());
                orderVO.setStype(type.getStype());
            }
            orderVO.setClient(JSON.parseObject(order.getClient(), PatientInfo.class));
            return orderVO;
        }).collect(Collectors.toList());
    }

    /**
     * 订单详情
     *
     * @param orderCode
     * @return
     */
    @Override
    public OrderVO detail(String orderCode) {
        MedOrder order = medOrderMapper.selectOne(new LambdaQueryWrapper<MedOrder>().eq(MedOrder::getOrderCode, orderCode));
        if (order == null) {
            return null;
        }
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);

        PatientInfo info = patientInfoMapper.selectById(order.getPatientInfoId());
        orderVO.setPatientInfo(info);

        EscortInfo escortInfo = escortInfoMapper.selectById(order.getEscortId());
        orderVO.setEscortInfo(escortInfo);

        Type type = typeMapper.selectById(order.getTypeId());
        if (Objects.nonNull(type)) {
            orderVO.setType(type.getTypeName());
            orderVO.setStype(type.getStype());
        }

        return orderVO;
    }

    /**
     * 用户发起预约订单
     *
     * @param dto
     */
    @Override
    @Transactional
    public String startOrder(OrderDTO dto) {
        AuthUser user = WebSecurityUtil.getCurrentUser();
        if (dto.getOrderStartTime().getTime() < System.currentTimeMillis()) {
            throw new RuntimeException("预约时间不能小于当前时间");
        }

        MedOrder medOrder = new MedOrder();
        BeanUtils.copyProperties(dto, medOrder);
        medOrder.setOrderPrice(dto.getOrderPrice());

        Type type = typeMapper.selectById(dto.getTypeId());
        if (Objects.nonNull(type) && type.getTypeName().contains("半天")) {
            medOrder.setOrderEndTime(new Date(dto.getOrderStartTime().getTime() + 12 * 60 * 60 * 1000));
        } else if (Objects.nonNull(type) && type.getTypeName().contains("全天")) {
            medOrder.setOrderEndTime(new Date(dto.getOrderStartTime().getTime() + 24 * 60 * 60 * 1000));
        }

        medOrder.setUserId(user.getId());
        medOrder.setOrderStatus(2);//待支付
        //设置唯一订单编号
        medOrder.setOrderCode(generateUniqueOrderCode());
        if (Objects.nonNull(dto.getClient())) {
            medOrder.setClient(JSON.toJSONString(dto.getClient()));
        }

        int insert = medOrderMapper.insert(medOrder);
        if (insert < 1) {
            throw new RuntimeException("预约失败");
        }

        // 设置定时任务，30分钟后检查是否支付
        scheduledTaskService.schedulePaymentCheck(medOrder.getOrderCode(), 30 * 60 * 1000);

        return medOrder.getOrderCode();//返回订单编号
    }

    /**
     * 陪诊员接取接取订单
     *
     * @param orderCode
     */
    @Override
    @Transactional
    public void takeOrder(String orderCode) {
        AuthUser currentUser = WebSecurityUtil.getCurrentUser();
        MedOrder order = medOrderMapper.selectOne(new LambdaQueryWrapper<MedOrder>().eq(MedOrder::getOrderCode, orderCode));
        if (order == null) {
            throw new BusinessException("订单不存在！请刷新后重试");
        }
        order.setOrderStatus(3); // 待陪诊
        medOrderMapper.updateById(order);

        // 更新陪诊员积分
        EscortInfo escortInfo = escortInfoMapper.selectById(currentUser.getId());
        Long score = escortInfo.getScore();
        Type type = typeMapper.selectById(order.getTypeId());
        if (Objects.nonNull(type)) {
            if (type.getTypeName().contains("半天")) escortInfo.setScore(score + 1);
            if (type.getTypeName().contains("全天")) escortInfo.setScore(score + 2);
            if (type.getTypeName().contains("不定时")) escortInfo.setScore(score + 3);
        }else {
            escortInfo.setScore(score + 1);
        }

        escortInfoMapper.updateById(escortInfo);
    }

    /**
     * 取消订单
     *
     * @param orderCode
     */
    @Override
    @Transactional
    public void cancelOrder(String orderCode) {
        MedOrder order = medOrderMapper.selectOne(new LambdaQueryWrapper<MedOrder>().eq(MedOrder::getOrderCode, orderCode).in(MedOrder::getOrderStatus, Arrays.asList(1, 2)));
        if (order == null) {
            throw new BusinessException("订单不存在！请刷新后重试");
        }
        order.setOrderStatus(6); //已取消
        medOrderMapper.updateById(order);
    }

    /**
     * 删除订单
     *
     * @param orderCode
     */
    @Override
    public void deleteOrder(String orderCode) {
        //删除已完成或者取消的
        medOrderMapper.delete(new LambdaQueryWrapper<MedOrder>().eq(MedOrder::getOrderCode, orderCode).in(MedOrder::getOrderStatus, Arrays.asList(1, 5, 6)));
    }

    /**
     * 支付接口
     *
     * @param orderCode
     */
    @Override
    @Transactional
    public void payOrder(String orderCode) {
        MedOrder order = medOrderMapper.selectOne(new LambdaQueryWrapper<MedOrder>().eq(MedOrder::getOrderCode, orderCode));
        if (order == null) {
            throw new BusinessException("订单不存在！请刷新后重试");
        }
        if (!order.getOrderStatus().equals(2)) {
            throw new BusinessException("当前订单状态不允许支付！");
        }
        order.setOrderStatus(1); // 待接单
        medOrderMapper.updateById(order);

        // 取消30分钟未支付检查定时任务
        scheduledTaskService.cancelPaymentCheck(orderCode);
    }

    /**
     * 完成订单
     *
     * @param orderCode
     */
    @Override
    @Transactional
    public void completeAppointment(String orderCode) {
        MedOrder order = medOrderMapper.selectOne(new LambdaQueryWrapper<MedOrder>().eq(MedOrder::getOrderCode, orderCode));
        if (order == null) {
            throw new BusinessException("订单不存在！请刷新后重试");
        }
        if (!order.getOrderStatus().equals(4)) {
            throw new BusinessException("当前订单状态不允许完成！");
        }
        order.setOrderStatus(5); // 已完成
        medOrderMapper.updateById(order);
        EscortInfo escortInfo = escortInfoMapper.selectById(order.getEscortId());
        escortInfo.setScore(escortInfo.getScore() + 1);
        escortInfoMapper.updateById(escortInfo);
    }

    /**
     * 订单编号格式化
     *
     * @return
     */
    private String generateUniqueOrderCode() {
        String dateStr = DateUtil.getDateTime(DateUtil.DATE_PATTERN.YYYYMMDDHHMMSS);
        int maxNumber = medOrderMapper.getMaxOrderNumberByDate(dateStr.substring(0, 8));
        return "O_" + dateStr + "_" + (maxNumber + 1);
    }
}
